﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Net;
using System.IO;

namespace OmegleStormer
{
    class Communications
    {
        string UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1";

        public ProxyInfo proxyInfo;
        public CookieContainer cookieMonster = new CookieContainer();

        public Communications()
        {
            System.Net.ServicePointManager.ServerCertificateValidationCallback += delegate(object sender,
                System.Security.Cryptography.X509Certificates.X509Certificate certificate,
                System.Security.Cryptography.X509Certificates.X509Chain chain,
                System.Net.Security.SslPolicyErrors sslPolicyErrors)
            { return true; };
        }


        public class ProxyInfo
        {
            public string IP { get; set; }
            public string Port { get; set; }
            public string User { get; set; }
            public string Password { get; set; }

            public override string ToString()
            {
                if (User != null) return string.Join(":", new string[] { IP, Port, User, Password });
                else return string.Join(":", new string[] { IP, Port });
            }
        }

        HttpWebRequest PrepareWebRequest(string url, string referer = "", string host = "", string accept = "")
        {
            var proxyBasicUri = new Uri(url);
            NetworkCredential nc = new NetworkCredential(proxyInfo.User, proxyInfo.Password);
            CredentialCache cache = new CredentialCache();
            cache.Add(proxyBasicUri, "Basic", nc);

            var request = HttpWebRequest.Create(proxyBasicUri) as HttpWebRequest;
            request.AllowAutoRedirect = false;
            request.CookieContainer = cookieMonster;
            request.UserAgent = UserAgent;
            request.Proxy = GetProxy();
            request.Accept = "application/json";
            request.Timeout = 60000;
            if (referer != "") request.Referer = referer;
            if (host != "") request.Host = host;
            if (accept != "") request.Accept = accept;

            return request;
        }

        public Stream PerformGetWithStream(string url, out WebResponse streamToClose, string referer = "", string host = "", string accept = "")
        {
            var request = PrepareWebRequest(url, referer, host, accept);
            request.Method = "GET";

            try
            {
                var response = request.GetResponse();
                (response as HttpWebResponse).Cookies = cookieMonster.GetCookies(request.RequestUri);
                streamToClose = response;
                return response.GetResponseStream();
            }
            catch (Exception ex)
            {
                var a = ex;
            }
            streamToClose = null;
            return null;
        }

        public string PerformGet(string url, string referer = "", string host = "", string accept = "")
        {
            var request = PrepareWebRequest(url, referer, host, accept);
            request.Method = "GET";
            return ReadResponseStream(request);
        }

        WebProxy GetProxy()
        {
            if (proxyInfo != null)
            {
                var proxy = new WebProxy(proxyInfo.IP, int.Parse(proxyInfo.Port));
                if (proxyInfo.User != "")
                    proxy.Credentials = new NetworkCredential(proxyInfo.User, proxyInfo.Password);
                return proxy;
            }
            return new WebProxy();
        }

        public string PerformPost(string url, PostData postData, string referer = "")
        {
            try
            {
                var request = PrepareWebRequest(url, referer);
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded; charset=utf-8";

                byte[] bytes = Encoding.ASCII.GetBytes(postData.ToString());
                request.ContentLength = bytes.Length;

                using (Stream writeStream = request.GetRequestStream())
                {
                    writeStream.Write(bytes, 0, bytes.Length);
                }
                return ReadResponseStream(request);
            }
            catch (WebException e)
            {
                if (e.Status == WebExceptionStatus.ProtocolError)
                {
                    WebResponse resp = e.Response;
                    using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
                    {
                        var f = sr.ReadToEnd();
                        return f;
                    }
                }
            }
            catch (Exception ex)
            {
                return null;
            }
            return null;
        }

        string ReadResponseStream(HttpWebRequest request)
        {
            try
            {
                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    response.Cookies = cookieMonster.GetCookies(request.RequestUri);
                    using (Stream responseStream = response.GetResponseStream())
                    {
                        using (StreamReader readStream = new StreamReader(responseStream, Encoding.UTF8))
                        {
                            readStream.BaseStream.ReadTimeout = 60000;
                            return readStream.ReadToEnd();
                        }
                    }
                }
            }
            catch (WebException e)
            {
                if (e.Status == WebExceptionStatus.ProtocolError)
                {
                    WebResponse resp = e.Response;
                    using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
                    {
                        var f = sr.ReadToEnd();
                        return f;
                    }
                }
            }
            catch (Exception ex)
            {
                return null;
            }
            return null;
        }

        public class PostData
        {
            private Dictionary<string, string> Values = new Dictionary<string, string>();

            public void AddValue(string key, string value)
            {
                Values.Add(key, HttpUtility.UrlEncode(value));
            }

            public override string ToString()
            {
                List<string> values = new List<string>();
                foreach (KeyValuePair<string, string> pair in Values)
                {
                    values.Add(pair.Key + "=" + pair.Value);
                }
                return string.Join("&", values.ToArray());
            }
        }


        public byte[] StreamToByteArray(Stream stream)
        {
            byte[] buffer = new byte[32768];
            using (MemoryStream ms = new MemoryStream())
            {
                while (true)
                {
                    int read = stream.Read(buffer, 0, buffer.Length);
                    if (read <= 0)
                        return ms.ToArray();
                    ms.Write(buffer, 0, read);
                }
            }
        }


    }
}
